package com.yao.mybatis.config;

import com.yao.mybatis.sqlnode.*;
import com.yao.mybatis.sqlsource.DynamicSqlSource;
import com.yao.mybatis.sqlsource.RawSqlSource;
import com.yao.mybatis.sqlsource.SqlSource;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.Text;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 解析sql语句成sqlSource
 *
 * @author Administrator
 */
public class XMLScriptParser {
    /**
     * 标注解析的sql是否应当存储到DynamicSqlSource中
     */
    private boolean isDynamic = false;
    /**
     * 存储sqlNode解析类，每种sqlNode对应不同的解析类
     */
    private Map<String, NodeHandler> nodeHandlerMap = new HashMap<>();

    public XMLScriptParser() {
        init();
    }

    /**
     * 解析sql语句
     *
     * @param element
     * @return
     */
    public SqlSource parse(Element element) {
        MixedSqlNode sqlNode = parseDynamicTags(element);
        // 再将SqlNode集合封装到SqlSource中
        SqlSource sqlSource = null;
        if (isDynamic) {
            sqlSource = new DynamicSqlSource(sqlNode);
        } else {
            sqlSource = new RawSqlSource(sqlNode);
        }
        // 由于带有#{}和${}、动态标签的sql处理方式不同，所以需要封装到不同的SqlSource中
        return sqlSource;
    }

    private void init() {
        nodeHandlerMap.put("if", new IfNodeHandler());
    }

    public MixedSqlNode parseDynamicTags(Element element) {
        List<SqlNode> sqlNodes = new ArrayList<>();
        int nodeCount = element.nodeCount();
        for (int i = 0; i < nodeCount; i++) {
            Node node = element.node(i);
            //判断node是文本还是标签
            if (node instanceof Text) {
                String sqlText = node.getText().trim();
                if (sqlText == null || "".equals(sqlText)) {
                    continue;
                }
                TextSqlNode textSqlNode = new TextSqlNode(sqlText);
                //判断文本中是否有${},如果有则要用DynamicSqlSource封装sqlNode
                if (textSqlNode.isDynamic()) {
                    sqlNodes.add(textSqlNode);
                    isDynamic = true;
                } else {
                    sqlNodes.add(new StaticTextSqlNode(sqlText));
                }

            } else if (node instanceof Element) {
                //子节点是动态标签，则需要继续解析，每种动态标签都有对应handler进行解析
                Element e = (Element) node;
                //获取标签名称
                String s = e.getName().toLowerCase();
                nodeHandlerMap.get(s).handleNode(e, sqlNodes,this);
                isDynamic = true;
            }

        }
        return new MixedSqlNode(sqlNodes);
    }
}
